<template>
  <div :class="{'d-dr-active': isActive,'d-dr-dragable': isDragAble}" class="d-drag-resizer">
    <slot></slot>
    <div v-show="!!des.length" class="d-dr-direction">
      <span v-show="hasDirection('nesw')" ref="nesw" class="d-dr-de-nesw"></span>
      <span v-show="hasDirection('n')" ref="n" class="d-dr-de d-dr-de-n"></span>
      <span v-show="hasDirection('e')" ref="e" class="d-dr-de d-dr-de-e"></span>
      <span v-show="hasDirection('s')" ref="s" class="d-dr-de d-dr-de-s"></span>
      <span v-show="hasDirection('w')" ref="w" class="d-dr-de d-dr-de-w"></span>
      <span v-show="hasDirection('nw')" ref="nw" class="d-dr-de d-dr-de-nw"></span>
      <span v-show="hasDirection('no')" ref="no" class="d-dr-de d-dr-de-no"></span>
      <span v-show="hasDirection('ne')" ref="ne" class="d-dr-de d-dr-de-ne"></span>
      <span v-show="hasDirection('ea')" ref="ea" class="d-dr-de d-dr-de-ea"></span>
      <span v-show="hasDirection('se')" ref="se" class="d-dr-de d-dr-de-se"></span>
      <span v-show="hasDirection('so')" ref="so" class="d-dr-de d-dr-de-so"></span>
      <span v-show="hasDirection('sw')" ref="sw" class="d-dr-de d-dr-de-sw"></span>
      <span v-show="hasDirection('we')" ref="we" class="d-dr-de d-dr-de-we"></span>
    </div>
  </div>
</template>

<script>
import { Drager } from '@daelui/dogjs/dist/components.js'

export default {
  props: {
    // 是否可拖拽
    isDragAble: {
      type: Boolean,
      default: true
    },
    // 是否可缩放
    isResizeAble: {
      type: Boolean,
      default: true
    },
    // 方向
    directions: {
      type: Array,
      default () {
        return [
          'n', 'e', 's', 'w', 'nw', 'no', 'ne', 'ea', 'se', 'so', 'sw', 'we'
        ]
      }
    },
    // 是否选中状态
    isActive: {
      type: Boolean,
      default: false
    }
  },

  data () {
    return {
      des: [],// 'nesw', 'n', 'e', 's', 'w', 'nw', 'no', 'ne', 'ea', 'se', 'so', 'sw', 'we'
      dragers: []
    }
  },

  methods: {
    // 获取移动的元素
    getParentEl () {
      return this.$el.parentNode
    },
    // 获取移动的元素
    getTargetEl () {
      return this.$el
    },
    // 开始监测
    handleDragStart (args) {
      let drager = args.drager
      let options = drager.options
      // 拖拽
      if (options.de === 'nesw') {
        this.$emit('drag-start', args)
      } else { // 缩放
        this.$emit('resize-start', args)
      }
    },
    // 移动监测
    handleDragMove (args) {
      let targetEl = this.getTargetEl()
      let drager = args.drager
      let options = drager.options
      let oldTargetStyle = args.oldTargetStyle
      let newTargetStyle = args.newTargetStyle
      if (options.de === 'nesw') {
        targetEl.style.top = newTargetStyle.top + 'px'
        targetEl.style.left = newTargetStyle.left + 'px'
        this.$emit('drag-move', args)
      }
      else if (options.de === 'se') {
        targetEl.style.width = oldTargetStyle.width + newTargetStyle.disX + 'px'
        targetEl.style.height = oldTargetStyle.height + newTargetStyle.disY + 'px'
        newTargetStyle.width = oldTargetStyle.width + newTargetStyle.disX
        newTargetStyle.height = oldTargetStyle.height + newTargetStyle.disY
        this.$emit('resize-move', args)
      }
      else if (options.de === 'ea' || options.de === 'e') {
        targetEl.style.width = oldTargetStyle.width + newTargetStyle.disX + 'px'
        newTargetStyle.width = oldTargetStyle.width + newTargetStyle.disX
        this.$emit('resize-move', args)
      }
      else if (options.de === 'so' || options.de === 's') {
        targetEl.style.height = oldTargetStyle.height + newTargetStyle.disY + 'px'
        newTargetStyle.height = oldTargetStyle.height + newTargetStyle.disY
        this.$emit('resize-move', args)
      }
    },
    // 结束监测
    handleDragEnd (args) {
      let drager = args.drager
      let options = drager.options
      if (options.de === 'nesw') {
        this.$emit('drag-end', args)
      }
      else if (/^(se|ea|e|so|s)$/.test(options.de)) {
        let targetEl = this.getTargetEl()
        let newTargetStyle = args.newTargetStyle
        newTargetStyle.width = parseFloat(targetEl.style.width)
        newTargetStyle.height = parseFloat(targetEl.style.height)
        this.$emit('resize-end', args)
      }
    },
    // 是否含有方向
    hasDirection (de) {
      return !!this.des.find(item => item === de)
    }
  },

  mounted () {
    // 方位
    let des = []
    // 拖拽
    if (this.isDragAble) {
      des.push('nesw')
    }
    // 缩放
    if (this.isResizeAble) {
      let defs = ['n', 'e', 's', 'w', 'nw', 'no', 'ne', 'ea', 'se', 'so', 'sw', 'we']
      let directions = this.directions
      directions = Array.isArray(directions) ? directions : []
      defs.forEach(item => {
        let de = directions.find(node => node === item)
        if (de) {
          des.push(de)
        }
      })
    }
    this.des = des

    // 事件绑定
    this.dragers = des.map(de => {
      let el = this.$refs[de]
      if (!el) {
        return false
      }
      // 拖拽绑定
      const drager = new Drager({
        el: el,
        targetEl: this.getTargetEl(),
        isSyncStyle: false,
        isSimulation: false,
        de
      })
      // 开始
      drager.$on('onDragStart', (args) => {
        this.handleDragStart(args)
      })
      // 移动
      drager.$on('onDragMove', (args) => {
        this.handleDragMove(args)
      })
      // 结束
      drager.$on('onDragEnd', (args) => {
        this.handleDragEnd(args)
      })

      return drager
    })
  },

  beforeDestroy () {
    this.dragers.forEach(item => {
      Drager.remove(item)
    })
  }
}
</script>

<style lang="less">
@unit: 8px;
.d-drag-resizer {
  &.d-dr-dragable {
    user-select: none;
  }
  &.d-dr-active:before,
  .d-dr-de-nesw {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
  }
  &:before {
    content: "";
    outline: 1px dashed #3391ff;
  }
  .d-dr-direction {
    .d-dr-de {
      display: none;
    }
  }
  &.d-dr-active {
    .d-dr-de {
      display: block;
    }
  }
  .d-dr-de {
    position: absolute;
    background: #fff;
    border: 1px solid #6c6c6c;
    z-index: 9;
  }
  .d-dr-de-n,.d-dr-de-e,
  .d-dr-de-s,.d-dr-de-w {
    border: none;
    background: transparent;
  }
  .d-dr-de-n {
    left: 0;
    right: 0;
    top: 0 - (@unit / 2);
    height: @unit;
  }
  .d-dr-de-e {
    top: 0;
    bottom: 0;
    right: 0 - (@unit / 2);
    width: @unit;
  }
  .d-dr-de-s {
    left: 0;
    right: 0;
    bottom: 0 - (@unit / 2);
    height: @unit;
  }
  .d-dr-de-w {
    top: 0;
    bottom: 0;
    left: 0 - (@unit / 2);
    width: @unit;
  }
  .d-dr-de-nw,.d-dr-de-se {
    cursor: nwse-resize;
  }
  .d-dr-de-no,.d-dr-de-n,
  .d-dr-de-so,.d-dr-de-s {
    cursor: ns-resize;
  }
  .d-dr-de-ne,.d-dr-de-sw {
    cursor: nesw-resize;
  }
  .d-dr-de-e,.d-dr-de-ea,
  .d-dr-de-we,.d-dr-de-w {
    cursor: ew-resize;
  }
  .d-dr-de-nw,.d-dr-de-no,
  .d-dr-de-ne,.d-dr-de-ea,
  .d-dr-de-se,.d-dr-de-so,
  .d-dr-de-sw,.d-dr-de-we {
    width: @unit;
    height: @unit;
  }
  .d-dr-de-nw {
    top: 0 - (@unit / 2);
    left: 0 - (@unit / 2);
  }
  .d-dr-de-no {
    top: 0 - (@unit / 2);
    left: 50%;
    margin-left: 0 - (@unit / 2);
  }
  .d-dr-de-ne {
    top: 0 - (@unit / 2);
    right: 0 - (@unit / 2);
  }
  .d-dr-de-ea {
    right: 0 - (@unit / 2);
    top: 50%;
    margin-top: 0 - (@unit / 2);
  }
  .d-dr-de-se {
    right: 0 - (@unit / 2);
    bottom: 0 - (@unit / 2);
  }
  .d-dr-de-so {
    bottom: 0 - (@unit / 2);
    left: 50%;
    margin-left: 0 - (@unit / 2);
  }
  .d-dr-de-sw {
    left: 0 - (@unit / 2);
    bottom: 0 - (@unit / 2);
  }
  .d-dr-de-we {
    left: 0 - (@unit / 2);
    top: 50%;
    margin-top: 0 - (@unit / 2);
  }
}
</style>
